package com.cnswhy.cloud.server.comsumer.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;

import javax.crypto.Mac;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 描述: 发送阿里云短信工具类
 * 版权: Copyright (c) 2019 
 * 公司: 小鹿科技
 * 作者: 张润泽 
 * 版本: 1.0 
 * 创建日期: 2019年10月21日 
 * 创建时间: 下午7:39:08
 */
@Slf4j
public class SendSmsUtil
{

    public static void main(String[] args) {
        try {
            JSONObject jsonObject = new JSONObject();

            jsonObject.put("code", "3280");
            SendSmsUtil.sendSms("18826426220","汇客通","SMS_168586949","LTAIlBFDDNv8oSjE","BwRCJaY2QwAFDkSG5twZhJkp3FQNjr",JSON.toJSONString(jsonObject));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * 描述：发送验证码
     * 作者：张润泽
     * 时间：2019年10月21日 下午7:47:19
     * @param mobile 手机号
     * @param templateCode 模板编号
     * @param content 内容
     * @return
     * @throws Exception
     */

    public static String sendSms(String mobile,String signName, String templateCode,String accessKeyId,String accessSecret, String content) throws Exception
    {
        //String accessKeyId = "LTAI4GAaooC3y7VvWyBzxfJa";
        //String accessSecret = "2hlRfulIwYFbiVknmmnBWhfTtnW2Vl";
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区
        Map<String, String> paras = new HashMap<String, String>();
        // 1. 系统参数
        paras.put("SignatureMethod", "HMAC-SHA1");
        paras.put("SignatureNonce", UUID.randomUUID().toString());
        paras.put("AccessKeyId", accessKeyId);
        paras.put("SignatureVersion", "1.0");
        paras.put("Timestamp", df.format(new java.util.Date()));
        // 2. 业务API参数
        paras.put("Action", "SendSms");
        paras.put("Version", "2017-05-25");
        paras.put("RegionId", "cn-hangzhou");
        paras.put("PhoneNumbers", mobile);
        //paras.put("SignName", "未来合创");
        paras.put("SignName", signName);
        if (StringUtils.isNotBlank(content))
        {
            paras.put("TemplateParam", content);
        }
        paras.put("TemplateCode", templateCode);
        paras.put("Format", "json");
        // 3. 去除签名关键字Key
        if (paras.containsKey("Signature"))
            paras.remove("Signature");
        // 4. 参数KEY排序
        TreeMap<String, String> sortParas = new TreeMap<String, String>();
        sortParas.putAll(paras);
        // 5. 构造待签名的字符串
        Iterator<String> it = sortParas.keySet().iterator();
        StringBuilder sortQueryStringTmp = new StringBuilder();
        while (it.hasNext())
        {
            String key = it.next();
            sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=")
                    .append(specialUrlEncode(paras.get(key)));
        }
        String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号
        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append("GET").append("&");
        stringToSign.append(specialUrlEncode("/")).append("&");
        stringToSign.append(specialUrlEncode(sortedQueryString));
        String sign = sign(accessSecret + "&", stringToSign.toString());
        // 6. 签名最后也要做特殊URL编码
        String signature = specialUrlEncode(sign);
        // 最终打印出合法GET请求的URL
        String url = "https://dysmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp;
        log.info("请求参数：" + url);
        String res = httpPostRequest(url);
        log.info("返回内容：" + res);
        return res;

    }
    /**
     * 描述：发送验证码
     * 作者：张润泽
     * 时间：2019年10月21日 下午7:47:19
     * @param mobile 手机号
     * @return
     * @throws Exception
     */
    public static String query(String mobile,String bizId,String accessKeyId,String accessSecret) throws Exception
    {
        //String accessKeyId = "LTAI4GAaooC3y7VvWyBzxfJa";
        //String accessSecret = "2hlRfulIwYFbiVknmmnBWhfTtnW2Vl";
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        df.setTimeZone(new java.util.SimpleTimeZone(0, "GMT"));// 这里一定要设置GMT时区
        Map<String, String> paras = new HashMap<String, String>();
        // 1. 系统参数
        paras.put("SignatureMethod", "HMAC-SHA1");
        paras.put("SignatureNonce", UUID.randomUUID().toString());
        paras.put("AccessKeyId", accessKeyId);
        paras.put("SignatureVersion", "1.0");
        paras.put("Timestamp", df.format(new java.util.Date()));
        // 2. 业务API参数
        paras.put("Action", "QuerySendDetails");
        paras.put("Version", "2017-05-25");
        paras.put("RegionId", "cn-hangzhou");
        paras.put("PhoneNumbers", mobile);
        paras.put("BizId", bizId);
        paras.put("Format", "json");
        // 3. 去除签名关键字Key
        if (paras.containsKey("Signature"))
            paras.remove("Signature");
        // 4. 参数KEY排序
        TreeMap<String, String> sortParas = new TreeMap<String, String>();
        sortParas.putAll(paras);
        // 5. 构造待签名的字符串
        Iterator<String> it = sortParas.keySet().iterator();
        StringBuilder sortQueryStringTmp = new StringBuilder();
        while (it.hasNext())
        {
            String key = it.next();
            sortQueryStringTmp.append("&").append(specialUrlEncode(key)).append("=")
                    .append(specialUrlEncode(paras.get(key)));
        }
        String sortedQueryString = sortQueryStringTmp.substring(1);// 去除第一个多余的&符号
        StringBuilder stringToSign = new StringBuilder();
        stringToSign.append("GET").append("&");
        stringToSign.append(specialUrlEncode("/")).append("&");
        stringToSign.append(specialUrlEncode(sortedQueryString));
        String sign = sign(accessSecret + "&", stringToSign.toString());
        // 6. 签名最后也要做特殊URL编码
        String signature = specialUrlEncode(sign);
        // 最终打印出合法GET请求的URL
        String url = "https://dysmsapi.aliyuncs.com/?Signature=" + signature + sortQueryStringTmp;
        log.info("请求参数：" + url);
        String res = httpPostRequest(url);
        log.info("返回内容：" + res);
        return res;
    }
    
    public static String specialUrlEncode(String value) throws Exception
    {
        return URLEncoder.encode(value, "UTF-8").replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
    }
    
    @SuppressWarnings("restriction")
    public static String sign(String accessSecret, String stringToSign) throws Exception
    {
        Mac mac = Mac.getInstance("HmacSHA1");
        mac.init(new javax.crypto.spec.SecretKeySpec(accessSecret.getBytes("UTF-8"), "HmacSHA1"));
        byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
        return new sun.misc.BASE64Encoder().encode(signData);
    }
    
    private static String httpPostRequest(String urlStr) throws Exception
    {
        OutputStream outputstream = null;
        BufferedReader in = null;
        try
        {
            URL url = new URL(urlStr);
            URLConnection httpurlconnection = url.openConnection();
            httpurlconnection.setConnectTimeout(10 * 1000);
            httpurlconnection.setDoOutput(true);
            httpurlconnection.setUseCaches(false);
            
            StringBuffer result = new StringBuffer();
            in = new BufferedReader(new InputStreamReader(httpurlconnection.getInputStream(), "UTF-8"));
            String line;
            while ((line = in.readLine()) != null)
            {
                result.append(line);
            }
            return result.toString();
        }
        catch (Exception ex)
        {
            throw new Exception("post请求异常：" + ex.getMessage());
        }
        finally
        {
            if (outputstream != null)
            {
                try
                {
                    outputstream.close();
                }
                catch (IOException e)
                {
                    outputstream = null;
                }
            }
            if (in != null)
            {
                try
                {
                    in.close();
                }
                catch (IOException e)
                {
                    in = null;
                }
            }
        }
    }
}
